package org.travel.app.controller;
import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.easysdk.factory.Factory;
import com.google.gson.JsonObject;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.travel.app.common.vo.ResultVO;
import org.travel.app.configure.AlipayConfiguration;
import org.travel.app.entity.Alipay;
import org.travel.app.entity.Order;
import org.travel.app.entity.ticket.TicketOrderMsg;
import org.travel.app.service.impl.OrderServiceImpl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author nmm
 * @date 2025-01-2025/1/4
 * @deriction njm......
 */
@RestController
@RequestMapping("/alipay")
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AliPayController extends BaseController{

    @Resource
    AlipayConfiguration aliPayConfig;

    @Autowired
    OrderServiceImpl orderService;

    @Autowired
    RedisTemplate <String,Object> redisTemplate;

    /**
     * 支付宝网官地址
     */
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";

    /**
     * 设置格式
     */
    private static final String FORMAT = "JSON";
    private static final String CHARSET = "utf-8";
    private static final String SIGN_TYPE = "RSA2";
    private static String QUICK_MSECURITY_PAY = "QUICK_MSECURITY_PAY";

    /**
     * web支付
     * @param aliPay
     * @param httpResponse
     * @param orderId
     * @throws Exception
     */
    @RequestMapping("/webPay") // &subject=xxx&traceNo=xxx&totalAmount=xxx
    public void pay(Alipay aliPay, HttpServletResponse httpResponse, @RequestParam String orderId) throws Exception {
        if (orderId != null) {
            System.out.println(orderId);
        }

        TicketOrderMsg order = orderService.getOrderByOrderId(orderId);
        //初始化客户端信息
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
        //设置回调地址
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("out_trade_no", order.getOrderId());
        jsonObject.set("total_amount", order.getTotalPrice());
        jsonObject.set("subject", order.getOrderName());
        jsonObject.set("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(jsonObject.toString());

        request.setReturnUrl("http://localhost:8080/travelAppManage/order/TestPayPort");
        //设置返回地址
        String form = "";
        try {
            // 调用SDK生成表单
            form = alipayClient.pageExecute(request).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + CHARSET);
        // 直接将完整的表单html输出到页面
        httpResponse.getWriter().write(form);
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }


    /**
     * app端支付
     * @param request
     * @param order
     * @return
     */
    @RequestMapping("/appPay")
    public ResultVO appAlipay(HttpServletRequest request,@RequestBody  Order order) {
        AlipayTradeWapPayRequest aliPayRequest = new AlipayTradeWapPayRequest();
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay

        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
        aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
        //实例化客户端

        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        TicketOrderMsg myOrder = orderService.getOrderByOrderId(order.getOrderId());
        String id = myOrder.getOrderId();
        BigDecimal totalPrice = myOrder.getTotalPrice();
        String orderName = myOrder.getOrderName();
        String bizContent = String.format(
                "{\"out_trade_no\":\"%s\","
                        + "\"total_amount\":\"%.2f\","
                        + "\"subject\":\"%s\","
                        + "\"body\":\"%s\","
                        + "\"timeout_express\":\"%s\","
                        + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\","
                        + "\"passback_params\":\"FAST_INSTANT_TRADE_PAY\"}", // 添加自定义参数
                id, totalPrice, orderName, "11", "30m"
        );
        aliPayRequest.setBizContent(bizContent);
        aliPayRequest.setNotifyUrl(aliPayConfig.getNotifyUrl());
        String apiUrl="";
        try {
            String result = alipayClient.sdkExecute(aliPayRequest).getBody();
            //调用sdkExecute 返回的是一个通用(web和app都可跳转的)url
            System.out.println(result);
            apiUrl=GATEWAY_URL+"?"+apiUrl+result;
            if (!result.isEmpty()){
                 redisTemplate.opsForValue().set("orderCurrentStats",1);
                 //未支付
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException("支付宝支付异常");
        }
        aliPayRequest.setReturnUrl("http://localhost:8080/travelAppManage/order/TestPayPort");
        return success(apiUrl);
    }


    /**
     * web端回调
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/notifyResult")  // 注意这里必须是POST接口
    public String payNotify(HttpServletRequest request) throws Exception {
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }

            String tradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");
            String alipayTradeNo = params.get("trade_no");
            // 支付宝验签
            if (Factory.Payment.Common().verifyNotify(params)) {
                // 验签通过
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
                // 更新订单未已支付

                Order order1=new Order();
                order1.setOrderId(tradeNo);
//                order.setCheckoutTime(params.get("gmt_payment"));
                orderService.updateOrderStatusByOrderId(order1);
            }
        }
        return "success";
    }


    /**
     * app端回调
     * @param request
     * @return
     */
    @RequestMapping("/notifyReturn")
    public String reCall(HttpServletRequest request){
       if (request.getParameter("passback_params").equals("FAST_INSTANT_TRADE_PAY")){
           Map<String, String> params = new HashMap<>();
           Map<String, String[]> requestParams = request.getParameterMap();
           for (String name : requestParams.keySet()) {
               params.put(name, request.getParameter(name));
           }
           // 商户订单号
           String tradeNo = params.get("out_trade_no");
           // 支付时间
           String gmtPayment = params.get("gmt_payment");
           // 支付宝交易号
           String alipayTradeNo = params.get("trade_no");
           // 获取订单信息
           Order order=new Order();
           order.setOrderId(tradeNo);
           orderService.updateOrderStatusByOrderId(order);
           //修改订单状态
           redisTemplate.opsForValue().set("orderCurrentStats",0);
           redisTemplate.expire("orderCurrentStats",30, TimeUnit.SECONDS);
           //设置过期时间为30秒(支付完成)
       }
       return "success";
    }

}